package com.hxzy.tms.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileChannel;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hxzy.tms.Assert;
import com.hxzy.tms.SessionHolder;
import com.hxzy.tms.dao.AttachmentDao;
import com.hxzy.tms.dao.UserDao;
import com.hxzy.tms.entity.Attachment;
import com.hxzy.tms.service.AttachmentService;

public class DefaultAttachmentService implements AttachmentService {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private AttachmentDao attachmentDao;
    private File destPath;
    private String downloadPath;

    public DefaultAttachmentService(AttachmentDao attachmentDao, UserDao userDao, File destPath) {
        this.attachmentDao = attachmentDao;
        this.destPath = destPath;

        if (this.destPath == null) {
            throw new IllegalArgumentException("destPath is null or empty.");
        }
        if (!this.destPath.isDirectory()) {
            throw new IllegalArgumentException(this.destPath.getAbsolutePath() + " must be a directory.");
        }
        if (!this.destPath.exists()) {
            throw new IllegalArgumentException(this.destPath.getAbsolutePath() + " is not exists.");
        }
        if (!this.destPath.canWrite()) {
            throw new IllegalArgumentException(this.destPath.getAbsolutePath() + " can't not write.");
        }
    }

    public String upload(String fileName, String contentType, File srcFile) {
        Assert.notEmpty(SessionHolder.get(), "must be login.");

        FileInputStream fis = null;
        FileOutputStream fos = null;
        File destFile = new File(destPath.getAbsolutePath() + File.separator + srcFile.getName());
        try {
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
        } catch (FileNotFoundException e) {
            logger.error("创建文件输入流或者输入流错误", e);
            return StringUtils.EMPTY;
        }

        // java nio 文件读写
        FileChannel input = fis.getChannel();
        FileChannel output = fos.getChannel();
        long size = 0L;
        try {
            size = input.size();
            long count = 0;
            int pos = 0;
            int buffer_size = 1024;
            while (pos < size) {
                count = (size - pos > buffer_size) ? buffer_size : (size - pos);
                pos += output.transferFrom(fis.getChannel(), pos, count);
            }
        } catch (IOException e) {
            logger.error("将源文件内容拷贝至目标文件错误", e);
            return StringUtils.EMPTY;
        } finally {
            try {
                fis.close();
                fos.close();
            } catch (IOException e) {
                logger.error("关闭文件输入流或者输入流错误", e);
                return StringUtils.EMPTY;
            }
        }

        Attachment attachment = new Attachment();
        attachment.setContentType(contentType);
        attachment.setFilename(fileName);
        attachment.setPath(destFile.getAbsolutePath());
        attachment.setSize(size);
        attachment.setCountOfDownload(0);
        attachment.setStatus(0);
        attachment.setUserCreate(SessionHolder.get());
        attachment.setUserModified(null);
        attachment.setGmtCreate((int) (System.currentTimeMillis() / 1000));
        attachment.setGmtModified(0);

        attachmentDao.create(attachment);

        return String.format(downloadPath, attachment.getId());
    }

    public InputStream download(Long id) {
        Attachment attachment = attachmentDao.read(Attachment.class, id);
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(new File(attachment.getPath()));
        } catch (FileNotFoundException e) {
            logger.error("创建文件输入流或者输入流错误", e);
            return null;
        }

        attachment.setCountOfDownload(attachment.getCountOfDownload() + 1);
        attachmentDao.update(attachment);

        return fileInputStream;
    }

    public Attachment get(Long id) {
        return attachmentDao.read(id);
    }

    public String getDownloadPath() {
        return downloadPath;
    }

    public void setDownloadPath(String downloadPath) {
        this.downloadPath = downloadPath;
    }

}
